*********************************************************************************
* Replication Stata code for
* "Estimating the Effect of Positivity about Immigrants on Vote Choice in the 2020 US Presidential Election
* Nations and Nationalism
*********************************************************************************

******************************************************************************************************************
* Open the VOTER panel dataset [https://www.voterstudygroup.org/data/voter-survey]
******************************************************************************************************************

clear all

use "voter_panel.dta" 

******************************************************************************************************************
* Weights
******************************************************************************************************************

sum weight_genpop_2020Sep
sum weight_genpop_2020Nov

******************************************************************************************************************
* Outcome variable
******************************************************************************************************************

codebook presvote_2020Nov
recode   presvote_2020Nov (1=0 "Trump") (2=1 "Biden") (3/max=.), gen(VOTEBT)
tab      presvote_2020Nov VOTEBT, mi

******************************************************************************************************************
* Key predictors
******************************************************************************************************************

* Feeling thermometer ratings [continuous]

clonevar FTIMMIG = ft_immig_2020Sep
clonevar FTWHITE = ft_white_2020Sep
clonevar FTBLACK = ft_black_2020Sep
clonevar FTHISPN = ft_latino_2020Sep
clonevar FTASIAN = ft_asian_2020Sep

recode FTIMMIG FTWHITE FTBLACK FTHISPN FTASIAN (min/-1 101/max = .)
sum    FTIMMIG FTWHITE FTBLACK FTHISPN FTASIAN

* Feeling thermometer ratings [absolute]

recode ft_immig_2020Sep  (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTIMMIG5)
recode ft_white_2020Sep  (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTWHITE5)
recode ft_black_2020Sep  (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTBLACK5)
recode ft_latino_2020Sep (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTHISPN5)
recode ft_asian_2020Sep  (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTASIAN5)

label define FT5 0 "0/25" 1 "26/49" 2 "50" 3 "Missing" 4 "51/75" 5 "76/99" 6 "100"

label values FTIMMIG5 FTWHITE5 FTBLACK5 FTHISPN5 FTASIAN5 FT5
tab1         FTIMMIG5 FTWHITE5 FTBLACK5 FTHISPN5 FTASIAN5

* Feeling thermometer ratings [relative]

gen     FTIMM3 = 9
replace FTIMM3 = 1 if (FTIMMIG >= 0 & FTIMMIG  <  50) & (FTIMMIG < FTWHITE) & (FTIMMIG < FTBLACK) & (FTIMMIG < FTHISPN) & (FTIMMIG < FTASIAN)
replace FTIMM3 = 3 if (FTIMMIG > 50 & FTIMMIG <= 100) & (FTIMMIG > FTWHITE) & (FTIMMIG > FTBLACK) & (FTIMMIG > FTHISPN) & (FTIMMIG > FTASIAN)
replace FTIMM3 = 2 if (FTIMMIG == FTWHITE) & (FTIMMIG == FTBLACK) & (FTIMMIG == FTHISPN) & (FTIMMIG == FTASIAN) 
replace FTIMM3 = 8 if FTIMMIG == . | FTWHITE == . | FTBLACK == . | FTHISPN == . | FTASIAN == .
replace FTIMM3 = . if weight_genpop_2020Sep == .
tab     FTIMM3
label   define FTIMM3 1 "Cold to immigrants" 2 "Indifferent to immigrants" 3 "Warm to immigrants" 8 "Missing" 9 "Residual" 
label   values FTIMM3 FTIMM3
tab     FTIMM3

* use for spot checking coding

order FTIMM3 ft_immig_2020Sep ft_white_2020Sep ft_black_2020Sep ft_latino_2020Sep ft_asian_2020Sep

******************************************************************************************************************
* Control variables
******************************************************************************************************************

codebook gender_2020Sep race_2020Sep birthyr_2020Sep educ_2020Sep marstat_2020Sep faminc_2020Sep religservice_2020Sep pid7_2020Sep

tab      gender_2020Sep
clonevar GENDER = gender_2020Sep

codebook race_2020Sep
recode   race_2020Sep (1=1 "White") (2=2 "Black") (3=3 "Hispanic") (4=4 "Asian") (5/8=5 "Other"), gen(RACE)
tab      race_2020Sep RACE

recode   RACE (1=0) (2/5=1), gen(RACENW)
tab      race_2020Sep RACENW

sum      birthyr_2020Sep
gen      AGE = 2020 - birthyr_2020Sep
tab      AGE
recode   AGE (18/30 = 1 "Age 18/30") (31/45 = 2 "Age 31/45") (46/60 = 3 "Age 46/60") (61/99 = 4 "Age 61+"), gen(AGEGRP)
tab      AGEGRP
tab      AGEGRP
clonevar EDUC = educ_2020Sep
tab      educ_2020Sep EDUC

codebook marstat_2020Sep
recode   marstat_2020Sep (1=1 "Married") (2/3=2 "Separated / Divorced") (4=4 "Widowed") (5=5 "Never married") (6=6 "Domestic/civil partnership"), gen(MARITAL)
tab      marstat_2020Sep MARITAL

tab      faminc_2020Sep
tab      faminc_2020Sep, nol
recode   faminc_2020Sep (1/3 = 1 "Less than $30k") (4/7 = 2 "$30k-$69k") (8/9 = 3 "$70k-$99k") (10/11 = 4 "$100k-$149k") (12/16 = 5 "$150k +") (97=97 "Prefer to not say"), gen(HHINCOME)
tab      faminc_2020Sep HHINCOME

codebook religservice_2020Sep 
recode   religservice_2020Sep (1/2=1 "More than once a week / Once a week") (3/4=2 "Once or twice a month / A few times a year") (5=3 "Seldom") (6=4 "Never") (7 98=5 "Don't know / Skipped"), gen(ATTEND)
tab      religservice_2020Sep ATTEND

tab      pid7_2020Sep
clonevar PID7 = pid7_2020Sep
tab      pid7_2020Sep PID7

clonevar PID3 = pid3_2020Sep
codebook pid3_2020Sep
recode   PID3 (5=4)
tab      pid3_2020Sep PID3

clonevar STATE = inputstate_2020Sep 

recode ft_blm_2020Sep    (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTBLM5)
recode ft_gay_2020Sep    (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTGAY5)
recode ft_muslim_2020Sep (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTMUSLM5)
recode ft_police_2020Sep (0/25=0) (26/49=1) (50=2) (51/75=4) (76/99=5) (100=6) (min/-1 101/max=3), gen(FTPOLICE5)
label  values FTBLM5 FTGAY5 FTMUSLM5 FTPOLICE5 FT5
tab1          FTBLM5 FTGAY5 FTMUSLM5 FTPOLICE5 

tab1 VOTEBT FTIMMIG5 FTIMM3 GENDER RACE AGEGRP EDUC MARITAL HHINCOME ATTEND PID7 STATE FTWHITE5 FTBLACK5 FTHISPN5 FTASIAN5 FTBLM5 FTGAY5 FTMUSLM5 FTPOLICE5 if weight_genpop_2020Nov != . & VOTEBT !=.

******************************************************************************************************************
* Figure 1. Distribution for FTs [using Sept 2020 weights]
******************************************************************************************************************

svyset [pw = weight_genpop_2020Sep]

sum weight_genpop_2020Nov if FTIMMIG!=. & FTWHITE!=. & FTBLACK!=. & FTHISPN!=. & FTASIAN!=.

svy: mean FTIMMIG FTWHITE FTBLACK FTHISPN FTASIAN, level(83.4)
svy: mean FTIMMIG, level(83.4)
svy: mean FTWHITE, level(83.4)
svy: mean FTBLACK, level(83.4)
svy: mean FTHISPN, level(83.4)
svy: mean FTASIAN, level(83.4)

svy: prop FTIMMIG5, level(83.4)
svy: prop FTWHITE5, level(83.4)
svy: prop FTBLACK5, level(83.4)
svy: prop FTHISPN5, level(83.4)
svy: prop FTASIAN5, level(83.4)

******************************************************************************************************************
* Figure 2. Subgroups [using Nov 2020 weights]
******************************************************************************************************************

svyset [pw = weight_genpop_2020Nov]

* Full sample

svy                              : logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f201
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* 

codebook GENDER

* GENDER == 1 : Men

svy, subpop(if GENDER == 1)      : logit VOTEBT ib2.FTIMMIG5          i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f202
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* GENDER == 2 : Women

svy, subpop(if GENDER == 2)      : logit VOTEBT ib2.FTIMMIG5          i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f203
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

*

codebook AGEGRP

* AGEGRP == 1 : 18-30

svy, subpop(if   AGEGRP == 1)    : logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE          i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f204
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* AGEGRP == 2 : 31-45

svy, subpop(if   AGEGRP == 2)    : logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE          i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f205
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* AGEGRP == 3 : 46-60

svy, subpop(if   AGEGRP == 3)    : logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE          i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f206
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* AGEGRP == 4 : 61+

svy, subpop(if   AGEGRP == 4)    : logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE          i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f207
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

*

codebook RACE

* RACE == 1 : Whites

svy, subpop(if   RACE == 1)      : logit VOTEBT ib2.FTIMMIG5 i.GENDER        i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f208
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* RACENW == 1 : Non-Whites

svy, subpop(if   RACENW == 1)    : logit VOTEBT ib2.FTIMMIG5 i.GENDER        i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f209
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* 

codebook pid3_2020Sep

* PID3 == 1 : Democrat

svy, subpop(if pid3_2020Sep == 1): logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND 
estimates store f210
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* PID3 == 3 : Independent

svy, subpop(if pid3_2020Sep == 3): logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND 
estimates store f211
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

* PID3 == 2 : Republican

svy, subpop(if pid3_2020Sep == 2): logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND
estimates store f212
margins, atmeans at(FTIMMIG5 = (0 2 6)) noatlegend level(83.4)

******************************************************************************************************************
* Figure 3. Absolute measure [using Nov 2020 weights]
******************************************************************************************************************

svyset [pw = weight_genpop_2020Nov]

codebook FTIMMIG5

* Controls for demographics

svy: logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND i.STATE
estimates store f31
margins, atmeans at(FTIMMIG5 = (0 1 2 4 5 6)) noatlegend level(83.4)

* Controls for demographics and partisanship

svy: logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND i.STATE ib4.PID7
estimates store f32
margins, atmeans at(FTIMMIG5 = (0 1 2 4 5 6)) noatlegend level(83.4)

* Controls for demographics, partisanship, and other groups

svy: logit VOTEBT ib2.FTIMMIG5 i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND i.STATE ib4.PID7 ib2.FTWHITE5 ib2.FTBLACK5 ib2.FTHISPN5 ib2.FTASIAN5 ib2.FTBLM5 ib2.FTGAY5 ib2.FTMUSLM5 ib2.FTPOLICE5
estimates store f33
margins, atmeans at(FTIMMIG5 = (0 1 2 4 5 6)) noatlegend level(83.4)

******************************************************************************************************************
* Figure 4. Relative measure [using Nov 2020 weights]
******************************************************************************************************************

svyset [pw = weight_genpop_2020Nov]

svy: prop FTIMM3, level(83.4)

* No controls

svy: logit VOTEBT i.FTIMM3
margins, atmeans at(FTIMM3 = (1 2 3)) noatlegend level(83.4)

* Controls for demographics

svy: logit VOTEBT ib2.FTIMM3  i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND i.STATE
estimates store f41
margins, atmeans at(FTIMM3 = (1 2 3)) noatlegend level(83.4)

* Controls for demographics and partisanship

svy: logit VOTEBT ib2.FTIMM3  i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND i.STATE ib4.PID7
estimates store f42
margins, atmeans at(PID7 = 4 FTIMM3 = (1 2 3)) noatlegend level(83.4)

* Controls for demographics, partisanship, and other groups

svy: logit VOTEBT ib2.FTIMM3  i.GENDER i.RACE i.AGEGRP i.EDUC i.MARITAL i.HHINCOME i.ATTEND i.STATE ib4.PID7 ib2.FTBLM5 ib2.FTGAY5 ib2.FTMUSLM5 ib2.FTPOLICE5
estimates store f43
margins, atmeans at(FTIMM3 = (1 2 3)) noatlegend level(83.4)

// esttab f41 f42 f43 using regression_output.rtf, b(%99.2f) se(%99.2f) starlevels(* 0.05) r2 ar2 pr2 nogaps label onecell replace
